package com.irenty.effectivej.ch02.objectreation;

import java.util.logging.Logger;

import org.testng.annotations.Test;

/*
 * Item 7: Avoid finalizers
 */
public class AvoidFinalizersTest {
	private final static Logger LOGGER = Logger
			.getLogger(AvoidFinalizersTest.class.getName());

	// Manual finalizer chaining
	@Override
	protected void finalize() throws Throwable {
		try {
			LOGGER.info("Manual finalizer running");
		} finally {
			super.finalize();
		}
	}

	/*
	 * never do anything time-critical in a finalizer, never depend on a
	 * finalizer to update critical persistent state.
	 * 
	 * if an uncaught exception is thrown during final- ization, the exception
	 * is ignored, and finalization of that object terminates
	 * 
	 * there is a severe performance penalty for using finalizers
	 * 
	 * Just provide an explicit termination method Explicit termination methods
	 * are typically used in combination with the try-finally construct to
	 * ensure termination.
	 * 
	 * First use is safety-net.
	 * 
	 * A second legitimate use of finalizers concerns objects with native peers.
	 * A native peer is a native object to which a normal object delegates via
	 * native meth- ods. Because a native peer is not a normal object, the
	 * garbage collector doesn’t know about it and can’t reclaim it when its
	 * Java peer is reclaimed. A finalizer is an appropriate vehicle for
	 * performing this task, assuming the native peer holds no critical
	 * resources.
	 */

	@Test
	public void testFinalizers() throws Exception {
		LOGGER.info("test finalizers");
	}

	// Finalizer Guardian idiom
	public static class Foo {
		// Sole purpose of this object is to finalize outer Foo object
		private final Object finalizerGuardian = new Object() {
			@Override
			protected void finalize() throws Throwable {
				LOGGER.info("Finalizing with finalizerGuardian");
			}
		};
	}

	/*
	 * In summary, don’t use finalizers except as a safety net or to terminate
	 * noncritical native resources. In those rare instances where you do use a
	 * finalizer, remember to invoke super.finalize. If you use a finalizer as a
	 * safety net, remember to log the invalid usage from the finalizer. Lastly,
	 * if you need to associate a finalizer with a public, nonfinal class,
	 * consider using a finalizer guardian, so finalization can take place even
	 * if a subclass finalizer fails to invoke super.finalize
	 */

}
